/**
 * @file appUser.c
 * @author  xiaowine (xiaowine@sina.cn)
 * @brief
 * @version 01.00
 * @date    2022-03-03
 *
 * @copyright Copyright (c) {2020}  xiaowine
 *
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2022-03-03 <td>1.0     <td>wangh     <td>内容
 * </table>
 * ******************************************************************
 * *                   .::::
 * *                 .::::::::
 * *                ::::::::::
 * *             ..:::::::::::
 * *          '::::::::::::
 * *            .:::::::::
 * *       '::::::::::::::..        女神助攻,流量冲天
 * *            ..::::::::::::.     永不宕机,代码无bug
 * *          ``:::::::::::::::
 * *           ::::``:::::::::'        .:::
 * *          ::::'   ':::::'       .::::::::
 * *        .::::'      ::::     .:::::::'::::
 * *       .:::'       :::::  .:::::::::' ':::::
 * *      .::'        :::::.:::::::::'      ':::::
 * *     .::'         ::::::::::::::'         ``::::
 * * ...:::           ::::::::::::'              ``::
 * *```` ':.          ':::::::::'                  ::::.
 * *                   '.:::::'                    ':'````.
 * ******************************************************************
 */

/* Private includes ----------------------------------------------------------*/
#include "appUser.h"
#include <stdio.h>
#include <string.h>
#include "blePro.h"
#include "cmsis_os2.h"  // CMSIS RTOS header file
#include "stm32g0xx_hal.h"
#include "tdsBsp.h"
#include "tm1640.h"
#include "usart.h"
#include "userLed.h"
#include "user_data.h"
#include "xw12.h"
/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
volatile _TKS_FLAGA_type keyTrg[4];
volatile uint16_t        k_count[2];
#define keyNUM        16
#define RESTAIN_TIMES 200  // 200 × 10ms = 2s
uint16_t keyBeepMask[2] = {0xffff, 0xffff};
#define KEYMASK     keyBeepMask[0]
#define RESTAINMASK keyBeepMask[1]
unsigned keyTime[keyNUM] = {0};
/*****beep***********************************************************/
_BEEP_STATE   beepState     = {0, 0, 0};
unsigned char beepCount     = 1;
unsigned char beepLongCount = 0;
/********************************************************************/
volatile _TKS_FLAGA_type bitFlag;
volatile _TKS_FLAGA_type BLEbitFlag;
volatile _TKS_FLAGA_type I2CbitFlag;
volatile _TKS_FLAGA_type I2CboardFlag;
/********************************************************************/
const uint8_t protocolHeader[2] = {0xff, 0xa5};
const uint8_t segment5C[3]      = {0x5c, 0x5c, 0x5c};
/********************************************************************/
uint8_t segmentValue[13]   = {0};
uint8_t segmentValueBK[13] = {0};
/********************************************************************/

/* Private function prototypes -----------------------------------------------*/
static void timerFlagOpt(void);
static void beepOpt(void);
static void keyScan(void);
static void i2cDataOpt(void);
static void refreshTxData(void);
static void segmentValueSet(void);
/* Private user code ---------------------------------------------------------*/

__NO_RETURN void userProc(void *argument)
{
    osThreadId_t thread_id = osThreadGetId();
    const char  *name      = osThreadGetName(thread_id);
    TM1640_Init(1);
    tdsUsartInit();
    printf("threadName:%s\r\n", name);
    osDelay(500);
    while (1) {
        timerFlagOpt();
        beepOpt();
        keyScan();
        userLed();
        i2cDataOpt();
        segmentValueSet();
        osDelay(10);
        tdsComService();
        if (FLAG_500MSF)
            tdsSend();
    }
}

static void timerFlagOpt(void)
{
    FLAG_63MSF  = TKS_63MSF;
    FLAG_250MSF = TKS_250MSF;
    FLAG_500MSF = TKS_500MSF;
    TKS_63MSF   = 0;
    TKS_250MSF  = 0;
    TKS_500MSF  = 0;
}

static void beepOpt(void)
{
    if (BEEPMODE) {
        beepFlag = 1;
        // GPIOB->BRR = GPIO_PIN_8; // BEEP = BEEP_ON; // BEEP = BEEP_ON;
        beepCount = 0;
    } else {
        if (beepLongCount) {
            if (FLAG_500MSF) {
                if (beepFlag) {
                    beepFlag = 0;
                    BEEP_OFF;
                    beepLongCount--;
                } else {
                    beepFlag = 1;
                    BEEP_ON;
                }
            }
            beepCount = 0;
            return;
        }
        if (FLAG_63MSF) {
            if (beepFlag) {
                beepFlag = 0;
                BEEP_OFF;
            } else if (beepCount) {
                beepCount--;
                beepFlag = 1;
                BEEP_ON;
            }
        }
    }
}
/**
 * @brief
 */
static void keyScan(void)
{
    uint16_t keyRestain = 0, keyData, i;
    keyData             = xw12ReadKey();

    *((uint16_t *)&keyTrg[0].byte) = keyData & (keyData ^ k_count[0]);
    k_count[0]                     = keyData;

    if ((*((uint16_t *)&keyTrg[0].byte) & KEYMASK) && (beepCount == 0)) {
        beepCount++;
    }

    for (i = 0; i < keyNUM; i++) {
        if (k_count[0] & (1 << i)) {
            if (keyTime[i] < RESTAIN_TIMES)
                keyTime[i]++;
            else
                keyRestain |= (1 << i);
        } else {
            // if (keyTime[i] > 0) // short press
            //     Key_Up_Trg |= (1 << i);
            // else
            //     Key_Up_Trg &= (~(1 << i));

            keyTime[i] = 0;
            keyRestain &= (~(1 << i));
        }
    }
    *((uint16_t *)&keyTrg[2].byte) = keyRestain & (keyRestain ^ k_count[1]);
    k_count[1]                     = keyRestain;
    if ((*((uint16_t *)&keyTrg[2].byte) & RESTAINMASK) && (beepCount == 0)) {
        beepCount++;
    }
}

static void i2cDataOpt(void)
{
    uint8_t checkSum, checkValue;
    if (I2CInOkFlag) {
        I2CInOkFlag = 0;
        if ((memcmp(protocolHeader, (void *)I2cDataIn, 2) != 0) || (I2cDataIn[3] > 14)) {
            return;
        }
        checkSum   = getCheckSum((void *)I2cDataIn);
        checkValue = I2cDataIn[I2cDataIn[3] + 4];
        if (checkSum == checkValue) {
            switch (I2cDataIn[2]) {
                case CMD_IDEL:
                    break;
                case CMD_KEY:
                    break;
                case CMD_LED:
                    beepState.byte = I2cDataIn[4];
                    memcpy((void *)&ledState[0].byte, (void *)&I2cDataIn[5], I2cDataIn[3] - 1);
                    if (BEEPMODE) {
                        beepCount     = 0;
                        beepLongCount = 0;
                    } else {
                        beepCount += BEEPSHORT;
                        beepLongCount += BEEPLONG;
                    }
                    break;
                case CMD_REG_UP:
                    regDataOk = 1;
                    memcpy((void *)bleTxBuff, (void *)I2cDataIn, 20);
                    break;
                case CMD_REG_DOWN:
                    break;
                case CMD_PARA:
                    memcpy(keyBeepMask, (void *)&I2cDataIn[4], 4);
                    boardPARAFlag = 1;
                    break;
                case CMD_SEGMENT:
                    memcpy(segmentValue, (void *)&I2cDataIn[4], 3);
                    memcpy(segmentValue + 10, (void *)&I2cDataIn[7], 3);

                    if (memcmp(segment5C, (void *)&I2cDataIn[10], 3)) {
                        SEGMENT_TDS0 = 1;
                        memcpy(segmentValue + 4, (void *)&I2cDataIn[10], 3);
                    } else {
                        uint16_t tds00 = tds0;
                        for (char i = 0; i < 3; i++) {
                            segmentValue[4 + i] = ch_table[tds00 % 10];
                            tds00 /= 10;
                        }
                        SEGMENT_TDS0 = 0;
                    }
                    if (memcmp(segment5C, (void *)&I2cDataIn[13], 3)) {
                        SEGMENT_TDS1    = 1;
                        segmentValue[9] = I2cDataIn[13];
                        segmentValue[8] = I2cDataIn[14];
                        segmentValue[7] = I2cDataIn[15];
                    } else {
                        uint16_t tds01 = tds1;
                        for (char i = 0; i < 3; i++) {
                            segmentValue[9 - i] = ch_table[tds01 % 10];
                            tds01 /= 10;
                        }
                        SEGMENT_TDS1 = 0;
                    }

                    break;
                default:
                    break;
            }
        }
    }
    refreshTxData();
}

static void refreshTxData(void)
{
    if (I2COutOkFlag) {
        I2COutOkFlag = 0;
        if (bleDataReday) {
            bleDataReday = 0;
            memcpy((void *)I2cDataOut, BleDataTemp, 20);
        } else {
            I2cDataOut[0] = 0xff;
            I2cDataOut[1] = 0xa5;
            I2cDataOut[2] = CMD_KEY;
            I2cDataOut[3] = 5;
            I2cDataOut[4] = I2CboardFlag.byte;
            memcpy((void *)&I2cDataOut[5], (void *)k_count, 4);
            I2cDataOut[9] = getCheckSum((void *)I2cDataOut);
        }
    }
}

static void segmentValueSet(void)
{
    if (memcmp(segmentValue, segmentValueBK, 13)) {
        TM1640_SendData(ADDR_START1640 + 1, segmentValue, 13);
        memcpy(segmentValueBK, segmentValue, 13);
    }
}
